######################################
# access_token 系统登陆相关的api接口
######################################
from typing import Union
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from schemas import Token, TokenData
from fastapi import APIRouter, Depends, HTTPException, status
from database import get_db
from fastapi.security import OAuth2PasswordRequestForm
import crud, schemas
from jose import JWTError, jwt
from utils import verify_password, APP_TOKEN_CONFIG
from fastapi import APIRouter
from api.api_v1.tools.json_resonse import sucessResonse, errorResponse

access_token_router = router = APIRouter(
    prefix="/v1",
    tags=["access_token_v1"],
    responses={404: {"description": "Not found"}},  # 请求异常返回数据
)

def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    """
    生成token
    :param data:
    :param expires_delta:
    :return:
    """
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=APP_TOKEN_CONFIG.ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    # 生成带有时间限制的token
    encoded_jwt = jwt.encode(to_encode, APP_TOKEN_CONFIG.SECRET_KEY, algorithm=APP_TOKEN_CONFIG.ALGORITHM)
    return encoded_jwt


def authenticate_user(db: Session, username: str, password: str, ):
    """
    认证用户，包括检测用户是否存在，密码校验。
    :param username:
    :param password:
    :param db:
    :return: 成功返回user
    """
    user = crud.get_user_by_username(db, username=username)  # 获取用户信息
    # 用户不存在
    if not user:
        return False
    # 校验密码失败
    if not verify_password(password, user.hashed_password):
        return False
    # 成功返回user
    return user

@router.post("/token", response_model=Token)
async def login_for_access_token(form_data: schemas.login, db: Session = Depends(get_db)):
    # 获取用户,如果没有或密码错误并提示错误.
    user = authenticate_user(db, form_data.username, form_data.password)
    if not user:
        return errorResponse(data = '用户名或密码错误!')

    if user.is_active:
        return errorResponse(data = '帐号已被禁用!')
    access_token_expires = timedelta(minutes=APP_TOKEN_CONFIG.ACCESS_TOKEN_EXPIRE_MINUTES)
    # 生成token
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return sucessResonse(data={"access_token": access_token, "token_type": "bearer"})